home *** CD-ROM | disk | FTP | other *** search
/ Delphi 5 for Professionals / DELPHI5.iso / AddOns / Components / Orpheus v3.02 / SETUP.EXE / %MAINDIR% / ovccmd.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-02-25  |  47.7 KB  |  1,480 lines

  1. {*********************************************************}
  2. {*                   OVCCMD.PAS 3.00                     *}
  3. {*     Copyright (c) 1995-99 TurboPower Software Co      *}
  4. {*                 All rights reserved.                  *}
  5. {*********************************************************}
  6.  
  7. {$I OVC.INC}
  8.  
  9. {$B-} {Complete Boolean Evaluation}
  10. {$I+} {Input/Output-Checking}
  11. {$P+} {Open Parameters}
  12. {$T-} {Typed @ Operator}
  13. {$W-} {Windows Stack Frame}
  14. {$X+} {Extended Syntax}
  15.  
  16. {$IFNDEF Win32}
  17. {$G+} {286 Instructions}
  18. {$N+} {Numeric Coprocessor}
  19.  
  20. {$C MOVEABLE,DEMANDLOAD,DISCARDABLE}
  21. {$ENDIF}
  22.  
  23. unit OvcCmd;
  24.   {-Translates messages into commands}
  25.  
  26. interface
  27.  
  28. uses
  29.   {$IFDEF Win32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF}
  30.   Classes, Forms, Menus, Messages, SysUtils,
  31.   OvcConst, OvcData, OvcExcpt, OvcMisc;
  32.  
  33. const
  34.   {default primary command/key table}
  35.   DefCommandTable : array[0..63] of TOvcCmdRec = (
  36.  {Key #1          Shift state #1
  37.   Key #2          Shift state #2              Command}
  38.  (Key1:VK_LEFT;   SS1:ss_None;
  39.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccLeft),
  40.  (Key1:VK_RIGHT;  SS1:ss_None;
  41.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccRight),
  42.  (Key1:VK_LEFT;   SS1:ss_Ctrl;
  43.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccWordLeft),
  44.  (Key1:VK_RIGHT;  SS1:ss_Ctrl;
  45.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccWordRight),
  46.  (Key1:VK_HOME;   SS1:ss_None;
  47.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccHome),
  48.  (Key1:VK_END;    SS1:ss_None;
  49.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccEnd),
  50.  (Key1:VK_DELETE; SS1:ss_None;
  51.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccDel),
  52.  (Key1:VK_BACK;   SS1:ss_None;
  53.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccBack),
  54.  (Key1:VK_BACK;   SS1:ss_Shift;
  55.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccBack),
  56.  (Key1:VK_PRIOR;  SS1:ss_Ctrl;
  57.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccTopOfPage),
  58.  (Key1:VK_NEXT;   SS1:ss_Ctrl;
  59.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccBotOfPage),
  60.  (Key1:VK_INSERT; SS1:ss_None;
  61.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccIns),
  62.  (Key1:VK_Z;      SS1:ss_Ctrl;
  63.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccUndo),
  64.  (Key1:VK_BACK;   SS1:ss_Alt;
  65.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccRestore),
  66.  (Key1:VK_UP;     SS1:ss_None;
  67.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccUp),
  68.  (Key1:VK_DOWN;   SS1:ss_None;
  69.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccDown),
  70.  (Key1:VK_RETURN; SS1:ss_Ctrl;
  71.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccNewLine),
  72.  (Key1:VK_LEFT;   SS1:ss_Shift;
  73.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendLeft),
  74.  (Key1:VK_RIGHT;  SS1:ss_Shift;
  75.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendRight),
  76.  (Key1:VK_HOME;   SS1:ss_Shift;
  77.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendHome),
  78.  (Key1:VK_END;    SS1:ss_Shift;
  79.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendEnd),
  80.  (Key1:VK_LEFT;   SS1:ss_Shift+ss_Ctrl;
  81.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtWordLeft),
  82.  (Key1:VK_RIGHT;  SS1:ss_Shift+ss_Ctrl;
  83.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtWordRight),
  84.  (Key1:VK_PRIOR;  SS1:ss_Shift;
  85.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendPgUp),
  86.  (Key1:VK_NEXT;   SS1:ss_Shift;
  87.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendPgDn),
  88.  (Key1:VK_UP;     SS1:ss_Shift;
  89.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendUp),
  90.  (Key1:VK_DOWN;   SS1:ss_Shift;
  91.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendDown),
  92.  (Key1:VK_HOME;   SS1:ss_Shift+ss_Ctrl;
  93.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtFirstPage),
  94.  (Key1:VK_END;    SS1:ss_Shift+ss_Ctrl;
  95.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtLastPage),
  96.  (Key1:VK_PRIOR;  SS1:ss_Shift+ss_Ctrl;
  97.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtTopOfPage),
  98.  (Key1:VK_NEXT;   SS1:ss_Shift+ss_Ctrl;
  99.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtBotOfPage),
  100.  (Key1:VK_DELETE; SS1:ss_Shift;
  101.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccCut),
  102.  (Key1:VK_X;      SS1:ss_Ctrl;
  103.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccCut),
  104.  (Key1:VK_INSERT; SS1:ss_Ctrl;
  105.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccCopy),
  106.  (Key1:VK_C;      SS1:ss_Ctrl;
  107.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccCopy),
  108.  (Key1:VK_INSERT; SS1:ss_Shift;
  109.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccPaste),
  110.  (Key1:VK_V;      SS1:ss_Ctrl;
  111.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccPaste),
  112.  (Key1:VK_PRIOR;  SS1:ss_None;
  113.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccPrevPage),
  114.  (Key1:VK_NEXT;   SS1:ss_None;
  115.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccNextPage),
  116.  (Key1:VK_HOME;   SS1:ss_Ctrl;
  117.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccFirstPage),
  118.  (Key1:VK_END;    SS1:ss_Ctrl;
  119.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccLastPage),
  120.  (Key1:VK_TAB;    SS1:ss_None;
  121.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccTab),
  122.  (Key1:VK_TAB;    SS1:ss_Ctrl;
  123.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccTab),
  124.  (Key1:VK_Z;      SS1:ss_Ctrl+ss_Shift;
  125.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccRedo),
  126.  (Key1:VK_0;      SS1:ss_Ctrl;
  127.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker0),
  128.  (Key1:VK_1;      SS1:ss_Ctrl;
  129.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker1),
  130.  (Key1:VK_2;      SS1:ss_Ctrl;
  131.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker2),
  132.  (Key1:VK_3;      SS1:ss_Ctrl;
  133.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker3),
  134.  (Key1:VK_4;      SS1:ss_Ctrl;
  135.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker4),
  136.  (Key1:VK_5;      SS1:ss_Ctrl;
  137.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker5),
  138.  (Key1:VK_6;      SS1:ss_Ctrl;
  139.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker6),
  140.  (Key1:VK_7;      SS1:ss_Ctrl;
  141.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker7),
  142.  (Key1:VK_8;      SS1:ss_Ctrl;
  143.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker8),
  144.  (Key1:VK_9;      SS1:ss_Ctrl;
  145.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccGotoMarker9),
  146.  (Key1:VK_0;      SS1:ss_Ctrl+ss_Shift;
  147.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker0),
  148.  (Key1:VK_1;      SS1:ss_Ctrl+ss_Shift;
  149.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker1),
  150.  (Key1:VK_2;      SS1:ss_Ctrl+ss_Shift;
  151.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker2),
  152.  (Key1:VK_3;      SS1:ss_Ctrl+ss_Shift;
  153.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker3),
  154.  (Key1:VK_4;      SS1:ss_Ctrl+ss_Shift;
  155.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker4),
  156.  (Key1:VK_5;      SS1:ss_Ctrl+ss_Shift;
  157.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker5),
  158.  (Key1:VK_6;      SS1:ss_Ctrl+ss_Shift;
  159.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker6),
  160.  (Key1:VK_7;      SS1:ss_Ctrl+ss_Shift;
  161.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker7),
  162.  (Key1:VK_8;      SS1:ss_Ctrl+ss_Shift;
  163.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker8),
  164.  (Key1:VK_9;      SS1:ss_Ctrl+ss_Shift;
  165.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccSetMarker9));
  166.  
  167.   {default WordStar command-key table}
  168.   DefWsMaxCommands = 40;
  169.   DefWsCommandTable : array[0..DefWsMaxCommands-1] of TOvcCmdRec = (
  170.  {Key #1          Shift state #1
  171.   Key #2          Shift state #2              Command}
  172.  (Key1:VK_S;      SS1:ss_Ctrl;
  173.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccLeft),
  174.  (Key1:VK_D;      SS1:ss_Ctrl;
  175.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccRight),
  176.  (Key1:VK_E;      SS1:ss_Ctrl;
  177.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccUp),
  178.  (Key1:VK_X;      SS1:ss_Ctrl;
  179.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccDown),
  180.  (Key1:VK_R;      SS1:ss_Ctrl;
  181.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccPrevPage),
  182.  (Key1:VK_C;      SS1:ss_Ctrl;
  183.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccNextPage),
  184.  (Key1:VK_W;      SS1:ss_Ctrl;
  185.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccScrollUp),
  186.  (Key1:VK_Z;      SS1:ss_Ctrl;
  187.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccScrollDown),
  188.  (Key1:VK_A;      SS1:ss_Ctrl;
  189.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccWordLeft),
  190.  (Key1:VK_F;      SS1:ss_Ctrl;
  191.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccWordRight),
  192.  (Key1:VK_Q;      SS1:ss_Ctrl;
  193.   Key2:VK_S;      SS2:ss_Wordstar;            Cmd:ccHome),
  194.  (Key1:VK_Q;      SS1:ss_Ctrl;
  195.   Key2:VK_D;      SS2:ss_Wordstar;            Cmd:ccEnd),
  196.  (Key1:VK_G;      SS1:ss_Ctrl;
  197.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccDel),
  198.  (Key1:VK_H;      SS1:ss_Ctrl;
  199.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccBack),
  200.  (Key1:VK_Y;      SS1:ss_Ctrl;
  201.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccDelLine),
  202.  (Key1:VK_Q;      SS1:ss_Ctrl;
  203.   Key2:VK_Y;      SS2:ss_Wordstar;            Cmd:ccDelEol),
  204.  (Key1:VK_V;      SS1:ss_Ctrl;
  205.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccIns),
  206.  (Key1:VK_T;      SS1:ss_Ctrl;
  207.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccDelWord),
  208.  (Key1:VK_P;      SS1:ss_Ctrl;
  209.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccCtrlChar),
  210.  (Key1:VK_Q;      SS1:ss_Ctrl;
  211.   Key2:VK_L;      SS2:ss_Wordstar;            Cmd:ccRestore),
  212.  (Key1:VK_Q;      SS1:ss_Ctrl;
  213.   Key2:VK_0;      SS2:ss_Wordstar;            Cmd:ccGotoMarker0),
  214.  (Key1:VK_Q;      SS1:ss_Ctrl;
  215.   Key2:VK_1;      SS2:ss_Wordstar;            Cmd:ccGotoMarker1),
  216.  (Key1:VK_Q;      SS1:ss_Ctrl;
  217.   Key2:VK_2;      SS2:ss_Wordstar;            Cmd:ccGotoMarker2),
  218.  (Key1:VK_Q;      SS1:ss_Ctrl;
  219.   Key2:VK_3;      SS2:ss_Wordstar;            Cmd:ccGotoMarker3),
  220.  (Key1:VK_Q;      SS1:ss_Ctrl;
  221.   Key2:VK_4;      SS2:ss_Wordstar;            Cmd:ccGotoMarker4),
  222.  (Key1:VK_Q;      SS1:ss_Ctrl;
  223.   Key2:VK_5;      SS2:ss_Wordstar;            Cmd:ccGotoMarker5),
  224.  (Key1:VK_Q;      SS1:ss_Ctrl;
  225.   Key2:VK_6;      SS2:ss_Wordstar;            Cmd:ccGotoMarker6),
  226.  (Key1:VK_Q;      SS1:ss_Ctrl;
  227.   Key2:VK_7;      SS2:ss_Wordstar;            Cmd:ccGotoMarker7),
  228.  (Key1:VK_Q;      SS1:ss_Ctrl;
  229.   Key2:VK_8;      SS2:ss_Wordstar;            Cmd:ccGotoMarker8),
  230.  (Key1:VK_Q;      SS1:ss_Ctrl;
  231.   Key2:VK_9;      SS2:ss_Wordstar;            Cmd:ccGotoMarker9),
  232.  (Key1:VK_K;      SS1:ss_Ctrl;
  233.   Key2:VK_0;      SS2:ss_Wordstar;            Cmd:ccSetMarker0),
  234.  (Key1:VK_K;      SS1:ss_Ctrl;
  235.   Key2:VK_1;      SS2:ss_Wordstar;            Cmd:ccSetMarker1),
  236.  (Key1:VK_K;      SS1:ss_Ctrl;
  237.   Key2:VK_2;      SS2:ss_Wordstar;            Cmd:ccSetMarker2),
  238.  (Key1:VK_K;      SS1:ss_Ctrl;
  239.   Key2:VK_3;      SS2:ss_Wordstar;            Cmd:ccSetMarker3),
  240.  (Key1:VK_K;      SS1:ss_Ctrl;
  241.   Key2:VK_4;      SS2:ss_Wordstar;            Cmd:ccSetMarker4),
  242.  (Key1:VK_K;      SS1:ss_Ctrl;
  243.   Key2:VK_5;      SS2:ss_Wordstar;            Cmd:ccSetMarker5),
  244.  (Key1:VK_K;      SS1:ss_Ctrl;
  245.   Key2:VK_6;      SS2:ss_Wordstar;            Cmd:ccSetMarker6),
  246.  (Key1:VK_K;      SS1:ss_Ctrl;
  247.   Key2:VK_7;      SS2:ss_Wordstar;            Cmd:ccSetMarker7),
  248.  (Key1:VK_K;      SS1:ss_Ctrl;
  249.   Key2:VK_8;      SS2:ss_Wordstar;            Cmd:ccSetMarker8),
  250.  (Key1:VK_K;      SS1:ss_Ctrl;
  251.   Key2:VK_9;      SS2:ss_Wordstar;            Cmd:ccSetMarker9));
  252.  
  253.   {default Orpheus Table command/key table}
  254.   DefGridMaxCommands = 38;
  255.   DefGridCommandTable : array[0..DefGridMaxCommands-1] of TOvcCmdRec = (
  256.  {Key #1          Shift state #1
  257.   Key #2          Shift state #2              Command}
  258.  (Key1:VK_LEFT;   SS1:ss_None;
  259.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccLeft),
  260.  (Key1:VK_RIGHT;  SS1:ss_None;
  261.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccRight),
  262.  (Key1:VK_LEFT;   SS1:ss_Ctrl;
  263.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccPageLeft),
  264.  (Key1:VK_RIGHT;  SS1:ss_Ctrl;
  265.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccPageRight),
  266.  (Key1:VK_HOME;   SS1:ss_None;
  267.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccHome),
  268.  (Key1:VK_END;    SS1:ss_None;
  269.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccEnd),
  270.  (Key1:VK_DELETE; SS1:ss_None;
  271.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccDel),
  272.  (Key1:VK_BACK;   SS1:ss_None;
  273.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccBack),
  274.  (Key1:VK_NEXT;   SS1:ss_Ctrl;
  275.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccBotOfPage),
  276.  (Key1:VK_PRIOR;  SS1:ss_Ctrl;
  277.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccTopOfPage),
  278.  (Key1:VK_INSERT; SS1:ss_None;
  279.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccIns),
  280.  (Key1:VK_Z;      SS1:ss_Ctrl;
  281.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccRestore),
  282.  (Key1:VK_UP;     SS1:ss_None;
  283.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccUp),
  284.  (Key1:VK_DOWN;   SS1:ss_None;
  285.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccDown),
  286.  (Key1:VK_LEFT;   SS1:ss_Shift;
  287.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendLeft),
  288.  (Key1:VK_RIGHT;  SS1:ss_Shift;
  289.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendRight),
  290.  (Key1:VK_HOME;   SS1:ss_Shift;
  291.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendHome),
  292.  (Key1:VK_END;    SS1:ss_Shift;
  293.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendEnd),
  294.  (Key1:VK_LEFT;   SS1:ss_Shift+ss_Ctrl;
  295.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtWordLeft),
  296.  (Key1:VK_RIGHT;  SS1:ss_Shift+ss_Ctrl;
  297.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtWordRight),
  298.  (Key1:VK_PRIOR;  SS1:ss_Shift;
  299.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendPgUp),
  300.  (Key1:VK_NEXT;   SS1:ss_Shift;
  301.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendPgDn),
  302.  (Key1:VK_UP;     SS1:ss_Shift;
  303.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendUp),
  304.  (Key1:VK_DOWN;   SS1:ss_Shift;
  305.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtendDown),
  306.  (Key1:VK_HOME;   SS1:ss_Shift+ss_Ctrl;
  307.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtFirstPage),
  308.  (Key1:VK_END;    SS1:ss_Shift+ss_Ctrl;
  309.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtLastPage),
  310.  (Key1:VK_PRIOR;  SS1:ss_Shift+ss_Ctrl;
  311.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtTopOfPage),
  312.  (Key1:VK_NEXT;   SS1:ss_Shift+ss_Ctrl;
  313.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccExtBotOfPage),
  314.  (Key1:VK_X;      SS1:ss_Ctrl;
  315.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccCut),
  316.  (Key1:VK_C;      SS1:ss_Ctrl;
  317.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccCopy),
  318.  (Key1:VK_V;      SS1:ss_Ctrl;
  319.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccPaste),
  320.  (Key1:VK_PRIOR;  SS1:ss_None;
  321.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccPrevPage),
  322.  (Key1:VK_HOME;   SS1:ss_Ctrl;
  323.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccFirstPage),
  324.  (Key1:VK_NEXT;   SS1:ss_None;
  325.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccNextPage),
  326.  (Key1:VK_END;    SS1:ss_Ctrl;
  327.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccLastPage),
  328.  (Key1:VK_UP;     SS1:ss_Ctrl;
  329.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccTopLeftCell),
  330.  (Key1:VK_DOWN;   SS1:ss_Ctrl;
  331.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccBotRightCell),
  332.  (Key1:VK_F2;     SS1:ss_None;
  333.   Key2:VK_NONE;   SS2:ss_None;                Cmd:ccTableEdit));
  334.  
  335. type
  336.   {command processor states}
  337.   TOvcProcessorState = (stNone, stPartial, stLiteral);
  338.  
  339.   {user command notify event}
  340.   TUserCommandEvent =
  341.     procedure(Sender : TObject; Command : Word)
  342.     of object;
  343.  
  344.   {forward class declarations}
  345.   TOvcCommandProcessor = class;
  346.  
  347.   TOvcCommandTable = class(TPersistent)
  348.   {.Z+}
  349.   protected {private}
  350.     FActive      : Boolean; {true to use this command table}
  351.     FCommandList : TList;   {list of command/key mappings}
  352.     FTableName   : string;  {the name of this command table}
  353.  
  354.     {property methods}
  355.     function GetCmdRec(Index : Integer) : TOvcCmdRec;
  356.       {-return the list item corresponding to "Index"}
  357.     function GetCount : Integer;
  358.       {-return the number of records in the list}
  359.     procedure PutCmdRec(Index : Integer; const CmdRec : TOvcCmdRec);
  360.       {-store a new command entry to the list at "Index" position}
  361.  
  362.     {internal methods}
  363.     procedure ctDisposeCommandEntry(P : POvcCmdRec);
  364.       {-dispose of a command entry record}
  365.     function ctNewCommandEntry(const CmdRec : TOvcCmdRec): POvcCmdRec;
  366.       {-allocate a new command entry record}
  367.     procedure ctReadData(Reader : TReader);
  368.       {-called to read the table from the stream}
  369.     procedure ctWriteData(Writer : TWriter);
  370.       {-called to store the table on the stream}
  371.  
  372.   protected
  373.     procedure DefineProperties(Filer : TFiler);
  374.       override;
  375.  
  376.   public
  377.     constructor Create;
  378.     destructor Destroy;
  379.       override;
  380.   {.Z-}
  381.  
  382.     function AddRec(const CmdRec : TOvcCmdRec) : Integer;
  383.       {-add a record to the list}
  384.     procedure Clear;
  385.       {-delete all records from the list}
  386.     procedure Delete(Index : Integer);
  387.       {-delete a record from the list}
  388.     procedure Exchange(Index1, Index2 : Integer);
  389.       {-exchange list locations of the two specified records}
  390.     function IndexOf(const CmdRec : TOvcCmdRec) : Integer;
  391.       {-return the index of the specified record}
  392.     procedure InsertRec(Index : Integer; const CmdRec : TOvcCmdRec);
  393.       {-insert a record at the specified index}
  394.     procedure LoadFromFile(const FileName : string);
  395.       {-read command entries from a text file}
  396.     procedure Move(CurIndex, NewIndex : Integer);
  397.       {-move one record to anothers index location}
  398.     procedure SaveToFile(const FileName: string);
  399.       {-write command entries to a text file}
  400.  
  401.     property Commands[Index : Integer] : TOvcCmdRec
  402.       read GetCmdRec write PutCmdRec; default;
  403.     property Count : Integer
  404.       read GetCount stored False;
  405.     property IsActive : Boolean
  406.       read FActive write FActive;
  407.     property TableName : string
  408.       read FTableName write FTableName;
  409.   end;
  410.  
  411.   TOvcCommandProcessor = class(TPersistent)
  412.   {.Z+}
  413.   protected {private}
  414.     {property variables}
  415.     FTableList  : TList;    {list of command tables}
  416.  
  417.     {internal variables}
  418.     cpState     : TOvcProcessorState;   {current state}
  419.     cpSaveKey   : Byte;     {saved last key processed}
  420.     cpSaveSS    : Byte;     {saved shift key state}
  421.  
  422.     {property methods}
  423.     function GetCount: Integer;
  424.       {-return the number of tables in the list}
  425.     function GetTable(Index : Integer) : TOvcCommandTable;
  426.       {-return the table referenced by "Index"}
  427.     procedure SetTable(Index : Integer; CT : TOvcCommandTable);
  428.       {-store a command table at position "Index"}
  429.  
  430.     {internal methods}
  431.     function cpFillCommandRec(Key1, ShiftState1,
  432.                               Key2, ShiftState2 : Byte;
  433.                               Command : Word) : TOvcCmdRec;
  434.       {-fill a command record}
  435.     procedure cpReadData(Reader: TReader);
  436.       {-called to read the command processor from the stream}
  437.     function cpScanTable(CT : TOvcCommandTable; Key, SFlags : Byte) : Word;
  438.       {-Scan the command table for a match}
  439.     procedure cpWriteData(Writer: TWriter);
  440.       {-called to store the command processor to the stream}
  441.  
  442.   protected
  443.     procedure DefineProperties(Filer: TFiler);
  444.       override;
  445.  
  446.   public
  447.     constructor Create;
  448.     destructor Destroy;
  449.       override;
  450.   {.Z-}
  451.  
  452.     procedure Add(CT : TOvcCommandTable);
  453.       {-add a command table to the list of tables}
  454.     procedure AddCommand(const TableName: string;
  455.                          Key1, ShiftState1,
  456.                          Key2, ShiftState2 : Byte;
  457.                          Command : Word);
  458.       {-add a command and key sequence to the command table}
  459.     procedure AddCommandRec(const TableName: string; const CmdRec : TOvcCmdRec);
  460.       {-add a command record to the command table}
  461.     procedure ChangeTableName(const OldName, NewName: string);
  462.       {-change the name of a table}
  463.     procedure Clear;
  464.       {-delete all tables from the list}
  465.     function CreateCommandTable(const TableName : string; Active : Boolean) : Integer;
  466.       {-create a command table and add it to the table list}
  467.     procedure Delete(Index : Integer);
  468.       {-delete the "Index" table from the list of tables}
  469.     procedure DeleteCommand(const TableName: string;
  470.                             Key1, ShiftState1,
  471.                             Key2, ShiftState2 : Byte);
  472.       {-delete a command and key sequence from a command table}
  473.     procedure DeleteCommandTable(const TableName : string);
  474.       {-delete a command table and remove it from the table list}
  475.     procedure Exchange(Index1, Index2 : Integer);
  476.       {-exchange list locations of the two specified command tables}
  477.     function GetCommandCount(const TableName : string) : Integer;
  478.       {-return the number of commands in the command table}
  479.     function GetCommandTable(const TableName : string) : TOvcCommandTable;
  480.       {-return a pointer to the specified command table or nil}
  481.     {.Z+}
  482.     procedure GetState(var State : TOvcProcessorState; var Key, Shift : Byte);
  483.       {-return the current status of the command processor}
  484.     {.Z-}
  485.     function GetCommandTableIndex(const TableName : string) : Integer;
  486.       {-return index to the specified command table or -1 for failure}
  487.     function LoadCommandTable(const FileName : string) : Integer; virtual;
  488.       {-creates and then fills a command table from a text file}
  489.     procedure ResetCommandProcessor;
  490.       {-reset the command processor}
  491.     procedure SaveCommandTable(const TableName, FileName : string); virtual;
  492.       {-save a command table to a text file}
  493.     procedure SetScanPriority(const Names : array of string);
  494.       {-reorder the list of tables based on this array}
  495.     {.Z+}
  496.     procedure SetState(State : TOvcProcessorState; Key, Shift : Byte);
  497.       {-set the state to the command processor}
  498.     {.Z-}
  499.     function Translate(var Msg : TMessage) : Word;
  500.       {-translate a message into a command}
  501.     function TranslateUsing(const Tables : array of string; var Msg : TMessage) : Word;
  502.       {-translate a message into a command using the given tables}
  503.     function TranslateKey(Key : Word; ShiftState : TShiftState) : Word;
  504.       {-translate a key and shift-state into a command}
  505.     function TranslateKeyUsing(const Tables : array of string; Key : Word; ShiftState : TShiftState) : Word;
  506.       {-translate a key and shift-state into a command using the given tables}
  507.  
  508.     property Count: Integer
  509.       read GetCount
  510.       stored False;
  511.  
  512.     property Table[Index : Integer]: TOvcCommandTable
  513.       read GetTable
  514.       write SetTable;
  515.       default;
  516.   end;
  517.  
  518.  
  519. implementation
  520.  
  521.  
  522. {*** TOvcCommandTable ***}
  523.  
  524. function TOvcCommandTable.AddRec(const CmdRec : TOvcCmdRec) : Integer;
  525. begin
  526.   Result := GetCount;
  527.   InsertRec(Result, CmdRec);
  528. end;
  529.  
  530. procedure TOvcCommandTable.Clear;
  531. var
  532.   I: Integer;
  533. begin
  534.   {dispose of all command records in the list}
  535.   for I := 0 to FCommandList.Count - 1 do
  536.     ctDisposeCommandEntry(FCommandList[I]);
  537.   {clear the list entries}
  538.   FCommandList.Clear;
  539. end;
  540.  
  541. constructor TOvcCommandTable.Create;
  542. begin
  543.   inherited Create;
  544.   FTableName := GetOrphStr(SCUnknownTable);
  545.   FActive := True;
  546.   FCommandList := TList.Create;
  547. end;
  548.  
  549. procedure TOvcCommandTable.ctDisposeCommandEntry(P : POvcCmdRec);
  550. begin
  551.   if Assigned(P) then
  552.     FreeMem(P, SizeOf(TOvcCmdRec));
  553. end;
  554.  
  555. function TOvcCommandTable.ctNewCommandEntry(const CmdRec : TOvcCmdRec): POvcCmdRec;
  556. begin
  557.   GetMem(Result, SizeOf(TOvcCmdRec));
  558.   Result^ := CmdRec;
  559. end;
  560.  
  561. procedure TOvcCommandTable.ctReadData(Reader : TReader);
  562. var
  563.   CmdRec : TOvcCmdRec;
  564.  
  565.   procedure ReadAndCompareTable(const CT : array of TOvcCmdRec);
  566.   var
  567.     I   : Integer;
  568.     Idx : Integer;
  569.   begin
  570.     {add all records initially}
  571.     for I := 0 to High(CT) do
  572.       AddRec(CT[I]);
  573.  
  574.     while not Reader.EndOfList do begin
  575.       with CmdRec, Reader do begin
  576.         Keys := ReadInteger;
  577.         Cmd := ReadInteger;
  578.       end;
  579.       {if keys on stream are dups replace default with redefinition}
  580.       Idx := IndexOf(CmdRec);
  581.       if Idx > -1 then begin
  582.         {if assigned to ccNone, remove instead of replace}
  583.         if CmdRec.Cmd = ccNone then
  584.           Delete(Idx)
  585.         else
  586.           Commands[Idx] := CmdRec
  587.       end else
  588.         AddRec(CmdRec);
  589.     end;
  590.   end;
  591.  
  592. begin
  593.   FTableName := Reader.ReadString;
  594.   FActive := Reader.ReadBoolean;
  595.   Reader.ReadListBegin;
  596.   Clear;
  597.  
  598.   if CompareText(GetOrphStr(SCDefaultTableName), FTableName) = 0 then
  599.     {if this is the "default" table, fill it with default commands}
  600.     ReadAndCompareTable(DefCommandTable)
  601.   else if CompareText(GetOrphStr(SCWordStarTableName), FTableName) = 0 then
  602.     {if this is the "wordstar" table, fill it with default commands}
  603.     ReadAndCompareTable(DefWsCommandTable)
  604.   else if CompareText(GetOrphStr(SCGridTableName), FTableName) = 0 then 
  605.     {if this is the "grid" table, fill it with default commands}
  606.     ReadAndCompareTable(DefGridCommandTable)
  607.   else begin
  608.   {otherwise, load complete command table from stream}
  609.     while not Reader.EndOfList do begin
  610.       with CmdRec, Reader do begin
  611.         Keys := ReadInteger;
  612.         Cmd := ReadInteger;
  613.       end;
  614.       AddRec(CmdRec);
  615.     end;
  616.   end;
  617.  
  618.   Reader.ReadListEnd;
  619. end;
  620.  
  621. procedure TOvcCommandTable.ctWriteData(Writer : TWriter);
  622. var
  623.   I      : Integer;
  624.   Cmdrec : TOvcCmdRec;
  625.  
  626.   procedure CompareAndWriteTable(const CT : array of TOvcCmdRec);
  627.   var
  628.     I, J : Integer;
  629.     Idx  : Integer;
  630.   begin
  631.     {find commands in the CT table but missing from this table}
  632.     for I := 0 to High(CT) do begin
  633.       Idx := IndexOf(CT[I]);
  634.       if Idx = -1 then begin
  635.         {not found, store and assign to ccNone}
  636.         with CT[I], Writer do begin
  637.           WriteInteger(Keys);
  638.           WriteInteger(ccNone);
  639.         end;
  640.       end;
  641.     end;
  642.  
  643.     {store all commands in new table if they are additions to the CT table}
  644.     for I := 0 to Count - 1 do begin
  645.       CmdRec := GetCmdRec(I);
  646.       {search CT for a match}
  647.       Idx := -1;
  648.       for J := 0 to High(CT) do begin
  649.         if (CmdRec.Keys = CT[J].Keys) and (CmdRec.Cmd = CT[J].Cmd) then begin
  650.           Idx := J;
  651.           Break;
  652.         end;
  653.       end;
  654.       if Idx = -1 then begin
  655.         {not found, store it}
  656.         with CmdRec, Writer do begin
  657.           WriteInteger(Keys);
  658.           WriteInteger(Cmd);
  659.         end;
  660.       end;
  661.     end;
  662.   end;
  663.  
  664. begin
  665.   Writer.WriteString(FTableName);
  666.   Writer.WriteBoolean(FActive);
  667.   Writer.WriteListBegin;
  668.  
  669.   {if this is the default command table, don't store command if not changed}
  670.   if CompareText(GetOrphStr(SCDefaultTableName), FTableName) = 0 then
  671.     {if this is the "default" command table, don't store commands if not changed}
  672.     CompareAndWriteTable(DefCommandTable)
  673.   else if CompareText(GetOrphStr(SCWordStarTableName), FTableName) = 0 then
  674.     {if this is the "wordstar" command table, don't store commands if not changed}
  675.     CompareAndWriteTable(DefWsCommandTable)
  676.   else if CompareText(GetOrphStr(SCGridTableName), FTableName) = 0 then
  677.     {if this is the "grid" command table, don't store commands if not changed}
  678.     CompareAndWriteTable(DefGridCommandTable)
  679.   else begin
  680.     {otherwise, save the complete table}
  681.     for I := 0 to Count - 1 do begin
  682.       CmdRec := GetCmdRec(I);
  683.       with CmdRec, Writer do begin
  684.         WriteInteger(Keys);
  685.         WriteInteger(Cmd);
  686.       end;
  687.     end;
  688.   end;
  689.  
  690.   Writer.WriteListEnd;
  691. end;
  692.  
  693. procedure TOvcCommandTable.DefineProperties(Filer : TFiler);
  694. begin
  695.   inherited DefineProperties(Filer);
  696.   Filer.DefineProperty('CommandList', ctReadData, ctWriteData, Count > 0);
  697. end;
  698.  
  699. procedure TOvcCommandTable.Delete(Index : Integer);
  700. begin
  701.   ctDisposeCommandEntry(FCommandList[Index]);
  702.   FCommandList.Delete(Index);
  703. end;
  704.  
  705. destructor TOvcCommandTable.Destroy;
  706. begin
  707.   Clear;
  708.   FCommandList.Free;
  709.   FCommandList := nil;
  710.  
  711.   inherited Destroy;
  712. end;
  713.  
  714. procedure TOvcCommandTable.Exchange(Index1, Index2 : Integer);
  715. begin
  716.   FCommandList.Exchange(Index1, Index2);
  717. end;
  718.  
  719. function TOvcCommandTable.GetCmdRec(Index : Integer) : TOvcCmdRec;
  720. begin
  721.   Result := POvcCmdRec(FCommandList[Index])^;
  722. end;
  723.  
  724. function TOvcCommandTable.GetCount : Integer;
  725. begin
  726.   Result := FCommandList.Count;
  727. end;
  728.  
  729. function TOvcCommandTable.IndexOf(const CmdRec : TOvcCmdRec) : Integer;
  730. begin
  731.   for Result := 0 to GetCount - 1 do
  732.     if CmdRec.Keys = GetCmdRec(Result).Keys then
  733.       Exit;
  734.   Result := -1;
  735. end;
  736.  
  737. procedure TOvcCommandTable.InsertRec(Index : Integer; const Cmdrec : TOvcCmdRec);
  738. begin
  739.   FCommandList.Expand.Insert(Index, ctNewCommandEntry(CmdRec));
  740. end;
  741.  
  742. procedure TOvcCommandTable.LoadFromFile(const FileName: string);
  743. var
  744.   T      : System.Text;
  745.   CmdRec : TOvcCmdRec;
  746. begin
  747.   Clear;  {erase current contents of list}
  748.   System.Assign(T, FileName);
  749.   System.Reset(T);
  750.   try {finally}
  751.     ReadLn(T, FTableName);  {get table name}
  752.     while not Eof(T) do begin
  753.       with CmdRec do ReadLn(T, Key1, SS1, Key2, SS2, Cmd);
  754.       AddRec(CmdRec);
  755.     end;
  756.   finally
  757.     System.Close(T);
  758.   end;
  759. end;
  760.  
  761. procedure TOvcCommandTable.Move(CurIndex, NewIndex : Integer);
  762. var
  763.   CmdRec : TOvcCmdRec;
  764. begin
  765.   if CurIndex <> NewIndex then begin
  766.     CmdRec := GetCmdRec(CurIndex);
  767.     Delete(CurIndex);
  768.     InsertRec(NewIndex, CmdRec);
  769.   end;
  770. end;
  771.  
  772. procedure TOvcCommandTable.PutCmdRec(Index : Integer; const CmdRec : TOvcCmdRec);
  773. var
  774.   P : POvcCmdRec;
  775. begin
  776.   P := FCommandList[Index];
  777.   try
  778.     FCommandList[Index] := ctNewCommandEntry(CmdRec);
  779.   finally
  780.     ctDisposeCommandEntry(P);
  781.   end;
  782. end;
  783.  
  784. procedure TOvcCommandTable.SaveToFile(const FileName: string);
  785. var
  786.   T  : System.Text;
  787.   I  : Integer;
  788.   CmdRec : TOvcCmdRec;
  789. begin
  790.   System.Assign(T, FileName);
  791.   System.Rewrite(T);
  792.   try {finally}
  793.     System.WriteLn(T, FTableName);  {save the table name}
  794.     for I := 0 to Count-1 do begin
  795.       CmdRec := GetCmdRec(I);
  796.       with CmdRec do
  797.         System.WriteLn(T, Key1:4, SS1:4, Key2:4, SS2:4, Cmd:6);
  798.     end;
  799.   finally
  800.     System.Close(T);
  801.   end;
  802. end;
  803.  
  804.  
  805. {*** TCommandProcessor ***}
  806.  
  807. procedure TOvcCommandProcessor.Add(CT : TOvcCommandTable);
  808.   {-add a command table to the list of tables}
  809. var
  810.   I    : Integer;
  811.   Base : string;
  812.   Name : string;
  813. begin
  814.   {make sure the table name is unique}
  815.   I := 0;
  816.  
  817.   Base := CT.TableName;
  818.  
  819.   {remove trailing numbers from the name, forming the base name}
  820.   while (Length(Base) > 1) and (Base[Length(Base)] in ['0'..'9']) do
  821.     {$IFDEF Win32}
  822.       {$IFOPT H+}
  823.       SetLength(Base, Length(Base)-1);
  824.       {$ELSE}
  825.       Dec(Byte(Base[0]));
  826.       {$ENDIF}
  827.     {$ELSE}
  828.     Dec(Byte(Base[0]));
  829.     {$ENDIF}
  830.  
  831.   Name := Base;
  832.  
  833.   {keep appending numbers until we find a unique name}
  834.   while GetCommandTable(Name) <> nil do begin
  835.     Inc(I);
  836.     Name := Base + Format('%d', [I]);
  837.   end;
  838.   if I > 0 then
  839.     CT.TableName := Name;
  840.  
  841.   {add table to the list}
  842.   FTableList.Add(CT);
  843. end;
  844.  
  845. procedure TOvcCommandProcessor.AddCommand(const TableName: string;
  846.                                           Key1, ShiftState1,
  847.                                           Key2, ShiftState2 : Byte;
  848.                                           Command : Word);
  849.   {-add a command and key sequence to the command table}
  850. var
  851.   CmdRec : TOvcCmdRec;
  852. begin
  853.   {fill temp command record}
  854.   CmdRec := cpFillCommandRec(Key1, ShiftState1, Key2, ShiftState2, Command);
  855.   {add the command}
  856.   AddCommandRec(TableName, CmdRec);
  857. end;
  858.  
  859. procedure TOvcCommandProcessor.AddCommandRec(const TableName: string; const CmdRec : TOvcCmdRec);
  860.   {-add a command record to the command table}
  861. var
  862.   TmpTbl : TOvcCommandTable;
  863. begin
  864.   {get the command table pointer}
  865.   TmpTbl := GetCommandTable(TableName);
  866.   if Assigned(TmpTbl) then begin
  867.     {does this key sequence conflict with any others}
  868.     if TmpTbl.IndexOf(CmdRec) = -1 then
  869.       {add the new command-key sequence}
  870.       TmpTbl.AddRec(CmdRec)
  871.     else
  872.       raise EDuplicateCommand.Create;
  873.   end else
  874.     raise ETableNotFound.Create;
  875. end;
  876.  
  877. procedure TOvcCommandProcessor.ChangeTableName(const OldName, NewName: string);
  878.   {-change the name of a table}
  879. var
  880.   TmpTbl : TOvcCommandTable;
  881. begin
  882.   TmpTbl := GetCommandTable(OldName);
  883.   if Assigned(TmpTbl) then
  884.     TmpTbl.TableName := NewName
  885.   else
  886.     raise ETableNotFound.Create;
  887. end;
  888.  
  889. procedure TOvcCommandProcessor.Clear;
  890.   {-delete all tables from the list}
  891. var
  892.   I : Integer;
  893. begin
  894.   {dispose of all command tables in the list}
  895.   for I := 0 to Count - 1 do
  896.     TOvcCommandTable(FTableList[I]).Free;
  897.   {clear the list entries}
  898.   FTableList.Clear;
  899. end;
  900.  
  901. function TOvcCommandProcessor.cpFillCommandRec(Key1, ShiftState1,
  902.                                             Key2, ShiftState2 : Byte;
  903.                                             Command : Word) : TOvcCmdRec;
  904.   {-fill a command record}
  905. begin
  906.   Result.Key1 := Key1;
  907.   Result.SS1 := ShiftState1;
  908.   Result.Key2 := Key2;
  909.   Result.SS2 := ShiftState2;
  910.   Result.Cmd := Command;
  911. end;
  912.  
  913. procedure TOvcCommandProcessor.cpReadData(Reader : TReader);
  914. var
  915.   TmpTbl : TOvcCommandTable;
  916. begin
  917.   {empty current table list}
  918.   Clear;
  919.   {read the start of list marker}
  920.   Reader.ReadListBegin;
  921.   while not Reader.EndOfList do begin
  922.     {create a command table}
  923.     TmpTbl := TOvcCommandTable.Create;
  924.     {load commands into the table}
  925.     TmpTbl.ctReadData(Reader);
  926.     {add the new table to the table list}
  927.     Add(TmpTbl);
  928.   end;
  929.   {read the end of list marker}
  930.   Reader.ReadListEnd;
  931. end;
  932.  
  933. function TOvcCommandProcessor.cpScanTable(CT : TOvcCommandTable; Key, SFlags : Byte) : Word;
  934.   {-Scan the command table for a match}
  935. var
  936.   J : Integer;
  937. begin
  938.   {assume failed match}
  939.   Result := ccNone;
  940.  
  941.   {scan the list of commands looking for a match}
  942.   for J := 0 to CT.Count-1 do with CT[J] do begin
  943.  
  944.     {do we already have a partial command}
  945.     if cpState = stPartial then begin
  946.       {does first key/shift state match the saved key/shift state?}
  947.       if (Key1 = cpSaveKey) and (SS1 = cpSaveSS) then
  948.         {does the key match?}
  949.         if (Key2 = Key) then
  950.           {does the shift state match?}
  951.           {or, is this the second key of a wordstar command}
  952.           if (SS2 = SFlags) or ((SS2 = ss_Wordstar) and
  953.              ((SFlags = ss_None) or (SFlags = ss_Ctrl))) then begin
  954.             Result := Cmd;  {return the command}
  955.             {if the command is ccCtrlChar, next key is literal}
  956.             if Cmd = ccCtrlChar then
  957.               cpState := stLiteral
  958.             else
  959.               cpState := stNone;
  960.             Exit;
  961.           end;
  962.     end else if (Key1 = Key) and (SS1 = SFlags) then begin
  963.       {we have an initial key match}
  964.       if Key2 = 0 then begin
  965.         {no second key}
  966.         Result := Cmd;  {return the command}
  967.         {if the command is ccCtrlChar, next key is literal}
  968.         if Cmd = ccCtrlChar then
  969.           cpState := stLiteral;
  970.         Exit;
  971.       end else begin
  972.         {it's a partial command}
  973.         Result := ccPartial;
  974.         cpState := stPartial;
  975.  
  976.         {save the key and shift state}
  977.         cpSaveKey := Key;
  978.         cpSaveSS := SFlags;
  979.         Exit;
  980.       end;
  981.     end;
  982.  
  983.   end;
  984. end;
  985.  
  986. procedure TOvcCommandProcessor.cpWriteData(Writer: TWriter);
  987. var
  988.   I : Integer;
  989. begin
  990.   {write the start of list marker}
  991.   Writer.WriteListBegin;
  992.   {have each table write itself}
  993.   for I := 0 to Count - 1 do
  994.     TOvcCommandTable(FTableList[I]).ctWriteData(Writer);
  995.   {write the end of list marker}
  996.   Writer.WriteListEnd;
  997. end;
  998.  
  999. constructor TOvcCommandProcessor.Create;
  1000. var
  1001.   I : Integer;
  1002.   S : string;
  1003. begin
  1004.   inherited Create;
  1005.  
  1006.   {create an empty command table list}
  1007.   FTableList  := TList.Create;
  1008.  
  1009.   {create and fill the default command table}
  1010.   S := GetOrphStr(SCDefaultTableName);
  1011.   CreateCommandTable(S, True {active});
  1012.   for I := 0 to High(DefCommandTable) do
  1013.     AddCommandRec(S, DefCommandTable[I]);
  1014.  
  1015.   {create and fill the WordStar command table}
  1016.   S := GetOrphStr(SCWordStarTableName);
  1017.   CreateCommandTable(S, False {not active});
  1018.   for I := 0 to DefWsMaxCommands-1 do
  1019.     AddCommandRec(S, DefWsCommandTable[I]);
  1020.  
  1021.   {create and fill the table(grid) command table}
  1022.   S := GetOrphStr(SCGridTableName);
  1023.   CreateCommandTable(S, False {not active});
  1024.   for I := 0 to DefGridMaxCommands-1 do
  1025.     AddCommandRec(S, DefGridCommandTable[I]);
  1026.  
  1027.   ResetCommandProcessor;
  1028. end;
  1029.  
  1030. function TOvcCommandProcessor.CreateCommandTable(const TableName : string; Active : Boolean) : Integer;
  1031.   {-create a command table and add it to the table list}
  1032. var
  1033.   TmpTbl : TOvcCommandTable;
  1034. begin
  1035.   TmpTbl := TOvcCommandTable.Create;
  1036.   TmpTbl.TableName := TableName;
  1037.   TmpTbl.IsActive := Active;
  1038.   Add(TmpTbl);
  1039.   Result := FTableList.IndexOf(TmpTbl);
  1040. end;
  1041.  
  1042. procedure TOvcCommandProcessor.DefineProperties(Filer: TFiler);
  1043. begin
  1044.   inherited DefineProperties(Filer);
  1045.   Filer.DefineProperty('TableList', cpReadData, cpWriteData, Count > 0);
  1046. end;
  1047.  
  1048. procedure TOvcCommandProcessor.Delete(Index : Integer);
  1049.   {-delete the "Index" table from the list of tables}
  1050. begin
  1051.   if (Index >= 0) and (Index < Count) then begin
  1052.     {delete the command table}
  1053.     TOvcCommandTable(FTableList[Index]).Free;
  1054.     {remove it from the list}
  1055.     FTableList.Delete(Index);
  1056.   end else
  1057.     raise ETableNotFound.Create;
  1058. end;
  1059.  
  1060. procedure TOvcCommandProcessor.DeleteCommand(const TableName: string;
  1061.                         Key1, ShiftState1,
  1062.                         Key2, ShiftState2 : Byte);
  1063. var
  1064.   I      : Integer;
  1065.   CmdRec     : TOvcCmdRec;
  1066.   TmpTbl : TOvcCommandTable;
  1067. begin
  1068.   {get the command table pointer}
  1069.   TmpTbl := GetCommandTable(TableName);
  1070.   if Assigned(TmpTbl) then begin
  1071.     {fill temp command record}
  1072.     CmdRec := cpFillCommandRec(Key1, ShiftState1, Key2, ShiftState2, 0);
  1073.     {find index of entry}
  1074.     I := TmpTbl.IndexOf(CmdRec);
  1075.     {if found, delete it -- no error if not found}
  1076.     if I > -1 then
  1077.       TmpTbl.Delete(I);
  1078.   end else
  1079.     raise ETableNotFound.Create;
  1080. end;
  1081.  
  1082. procedure TOvcCommandProcessor.DeleteCommandTable(const TableName : string);
  1083.   {-delete a command table and remove from the table list}
  1084. var
  1085.   I      : Integer;
  1086.   TmpTbl : TOvcCommandTable;
  1087. begin
  1088.   TmpTbl := GetCommandTable(TableName);;
  1089.   if Assigned(TmpTbl) then begin
  1090.     I := FTableList.IndexOf(TmpTbl);
  1091.     Delete(I);
  1092.   end else
  1093.     raise ETableNotFound.Create;
  1094. end;
  1095.  
  1096. destructor TOvcCommandProcessor.Destroy;
  1097. begin
  1098.   if Assigned(FTableList) then begin
  1099.     Clear;
  1100.     FTableList.Free;
  1101.   end;
  1102.   inherited Destroy;
  1103. end;
  1104.  
  1105. procedure TOvcCommandProcessor.Exchange(Index1, Index2 : Integer);
  1106.   {-exchange list locations of the two specified command tables}
  1107. begin
  1108.   FTableList.Exchange(Index1, Index2);
  1109. end;
  1110.  
  1111. function TOvcCommandProcessor.GetTable(Index : Integer) : TOvcCommandTable;
  1112.   {-return the table referenced by "Index"}
  1113. begin
  1114.   Result := TOvcCommandTable(FTableList[Index]);
  1115. end;
  1116.  
  1117. function TOvcCommandProcessor.GetCommandCount(const TableName : string) : Integer;
  1118.   {-return the number of commands in the command table}
  1119. var
  1120.   TmpTbl : TOvcCommandTable;
  1121. begin
  1122.   {get the command table pointer}
  1123.   TmpTbl := GetCommandTable(TableName);
  1124.   if Assigned(TmpTbl) then
  1125.     Result := TmpTbl.Count
  1126.   else
  1127.     raise ETableNotFound.Create;
  1128. end;
  1129.  
  1130. function TOvcCommandProcessor.GetCommandTable(const TableName : string) : TOvcCommandTable;
  1131.   {-return a pointer to the specified command table or nil}
  1132. var
  1133.   I : Integer;
  1134. begin
  1135.   Result := nil;
  1136.   for I := 0 To Count-1 do
  1137.     if UpperCase(TOvcCommandTable(FTableList[I]).TableName) = UpperCase(TableName) then begin
  1138.       Result := FTableList[I];
  1139.       Break;
  1140.     end;
  1141. end;
  1142.  
  1143. function TOvcCommandProcessor.GetCommandTableIndex(const TableName : string) : Integer;
  1144.   {-return index to the specified command table or -1 for failure}
  1145. var
  1146.   I : Integer;
  1147. begin
  1148.   Result := -1;
  1149.   for I := 0 To Count-1 do
  1150.     if UpperCase(TOvcCommandTable(FTableList[I]).TableName) = UpperCase(TableName) then begin
  1151.       Result := I;
  1152.       Break;
  1153.     end;
  1154. end;
  1155.  
  1156. function TOvcCommandProcessor.GetCount : Integer;
  1157.   {-return the number of tables in the list}
  1158. begin
  1159.   Result := FTableList.Count;
  1160. end;
  1161.  
  1162. procedure TOvcCommandProcessor.GetState(var State : TOvcProcessorState; var Key, Shift : Byte);
  1163. begin
  1164.   State := cpState;
  1165.   Key := cpSaveKey;
  1166.   Shift := cpSaveSS;
  1167. end;
  1168.  
  1169. function TOvcCommandProcessor.LoadCommandTable(const FileName : string) : Integer;
  1170.   {-creates and then fills a command table from a text file}
  1171. var
  1172.   TmpTbl : TOvcCommandTable;
  1173. begin
  1174.   TmpTbl := TOvcCommandTable.Create;
  1175.   try
  1176.     TmpTbl.LoadFromFile(FileName);
  1177.     Add(TmpTbl);
  1178.     Result := FTableList.IndexOf(TmpTbl);
  1179.   except
  1180.     TmpTbl.Free;
  1181.     raise;
  1182.   end;
  1183. end;
  1184.  
  1185. procedure TOvcCommandProcessor.ResetCommandProcessor;
  1186.   {-reset the command processor}
  1187. begin
  1188.   cpState   := stNone;
  1189.   cpSaveKey := VK_NONE;
  1190.   cpSaveSS  := 0;
  1191. end;
  1192.  
  1193. procedure TOvcCommandProcessor.SaveCommandTable(const TableName, FileName : string);
  1194.   {-save a command table to a text file}
  1195. var
  1196.   TmpTbl : TOvcCommandTable;
  1197. begin
  1198.   TmpTbl := GetCommandTable(TableName);
  1199.   if Assigned(TmpTbl) then
  1200.     TmpTbl.SaveToFile(FileName);
  1201. end;
  1202.  
  1203. procedure TOvcCommandProcessor.SetScanPriority(const Names : array of string);
  1204.   {-reorder the list of tables based on this array}
  1205. var
  1206.   I      : Integer;
  1207.   Idx    : Integer;
  1208.   TmpTbl : TOvcCommandTable;
  1209. begin
  1210.   for I := 0 to Pred(High(Names)) do begin
  1211.     TmpTbl := GetCommandTable(Names[I]);
  1212.     if Assigned(TmpTbl) then begin
  1213.       Idx := FTableList.IndexOf(TmpTbl);
  1214.       if (Idx > -1) and (Idx <> I) then
  1215.         Exchange(I, Idx);
  1216.     end;
  1217.   end;
  1218. end;
  1219.  
  1220. procedure TOvcCommandProcessor.SetTable(Index : Integer; CT : TOvcCommandTable);
  1221.   {-store a command table at position "Index"}
  1222. var
  1223.   P : TOvcCommandTable;
  1224. begin
  1225.   if (Index >= 0) and (Index < Count) then begin
  1226.     P := FTableList[Index];
  1227.     FTableList[Index] := CT;
  1228.     P.Free;
  1229.   end else
  1230.     raise ETableNotFound.Create;
  1231. end;
  1232.  
  1233. procedure TOvcCommandProcessor.SetState(State : TOvcProcessorState; Key, Shift : Byte);
  1234. begin
  1235.   cpState := State;
  1236.   cpSaveKey := Key;
  1237.   cpSaveSS := Shift;
  1238. end;
  1239.  
  1240. function TOvcCommandProcessor.Translate(var Msg : TMessage) : Word;
  1241.   {-translate a message into a command}
  1242. var
  1243.   Command : Word;
  1244.   I       : Integer;
  1245.   K       : Byte;        {message key code}
  1246.   SS      : Byte;        {shift flags}
  1247. begin
  1248.   {accept the key if no match found}
  1249.   Result := ccAccept;
  1250.  
  1251.   {check for shift state keys, note partial status and exit}
  1252.   K := Lo(Msg.wParam);
  1253.   case K of
  1254.     VK_SHIFT,     {shift}
  1255.     VK_CONTROL,   {ctrl}
  1256.     VK_ALT,       {alt}
  1257.     VK_CAPITAL,   {caps lock}
  1258.     VK_NUMLOCK,   {num lock}
  1259.     VK_SCROLL :   {scroll lock}
  1260.       begin
  1261.         {if we had a partial command before, we still do}
  1262.         if cpState = stPartial then
  1263.           Result := ccPartial;
  1264.         Exit;
  1265.       end;
  1266.   end;
  1267.  
  1268.   {exit if this key is to be interpreted literally}
  1269.   if cpState = stLiteral then begin
  1270.     cpState := stNone;
  1271.     Exit;
  1272.   end;
  1273.  
  1274.   {get the current shift flags}
  1275.   SS := GetShiftFlags;
  1276.  
  1277.   Command := ccNone;
  1278.   for I := 0 to Count-1 do
  1279.     if TOvcCommandTable(FTableList[I]).IsActive then begin
  1280.       Command := cpScanTable(FTableList[I], K, SS);
  1281.       if Command <> ccNone then
  1282.         Break;
  1283.     end;
  1284.  
  1285.   {if we found a match, return command and exit}
  1286.   if Command <> ccNone then begin
  1287.     Result := Command;
  1288.     Exit;
  1289.   end;
  1290.  
  1291.   {if we had a partial command, suppress this key}
  1292.   if cpState = stPartial then
  1293.     Result:= ccSuppress;
  1294.  
  1295.   cpState := stNone;
  1296. end;
  1297.  
  1298. function TOvcCommandProcessor.TranslateKey(Key : Word; ShiftState : TShiftState) : Word;
  1299.   {-translate a key and shift-state into a command}
  1300. var
  1301.   Command : Word;
  1302.   I       : Integer;
  1303.   SS      : Byte;        {shift flags}
  1304. begin
  1305.   {accept the key if no match found}
  1306.   Result := ccAccept;
  1307.  
  1308.   {check for shift state keys, note partial status and exit}
  1309.   case Key of
  1310.     VK_SHIFT,     {shift}
  1311.     VK_CONTROL,   {ctrl}
  1312.     VK_ALT,       {alt}
  1313.     VK_CAPITAL,   {caps lock}
  1314.     VK_NUMLOCK,   {num lock}
  1315.     VK_SCROLL :   {scroll lock}
  1316.       begin
  1317.         {if we had a partial command before, we still do}
  1318.         if cpState = stPartial then
  1319.           Result := ccPartial;
  1320.         Exit;
  1321.       end;
  1322.   end;
  1323.  
  1324.   {exit if this key is to be interpreted literally}
  1325.   if cpState = stLiteral then begin
  1326.     cpState := stNone;
  1327.     Exit;
  1328.   end;
  1329.  
  1330.   {get the current shift flags}
  1331.   SS := (Ord(ssCtrl in ShiftState) * ss_Ctrl) +
  1332.         (Ord(ssShift in ShiftState) * ss_Shift) +
  1333.         (Ord(ssAlt in ShiftState) * ss_Alt);
  1334.  
  1335.   Command := ccNone;
  1336.   for I := 0 to Count-1 do
  1337.     if TOvcCommandTable(FTableList[I]).IsActive then begin
  1338.       Command := cpScanTable(FTableList[I], Key, SS);
  1339.       if Command <> ccNone then
  1340.         Break;
  1341.     end;
  1342.  
  1343.   {if we found a match, return command and exit}
  1344.   if Command <> ccNone then begin
  1345.     Result := Command;
  1346.     Exit;
  1347.   end;
  1348.  
  1349.   {if we had a partial command, suppress this key}
  1350.   if cpState = stPartial then
  1351.     Result:= ccSuppress;
  1352.  
  1353.   cpState := stNone;
  1354. end;
  1355.  
  1356. function TOvcCommandProcessor.TranslateUsing(const Tables : array of string; var Msg : TMessage) : Word;
  1357.   {-translate a message into a command using the given tables}
  1358. var
  1359.   TmpTbl  : TOvcCommandTable;
  1360.   Command : Word;
  1361.   I       : Integer;
  1362.   K       : Byte;        {message key code}
  1363.   SS      : Byte;        {shift flags}
  1364. begin
  1365.   {accept the key if no match found}
  1366.   Result := ccAccept;
  1367.  
  1368.   {check for shift state keys, note partial status and exit}
  1369.   K := Lo(Msg.wParam);
  1370.   case K of
  1371.     VK_SHIFT,     {shift}
  1372.     VK_CONTROL,   {ctrl}
  1373.     VK_ALT,       {alt}
  1374.     VK_CAPITAL,   {caps lock}
  1375.     VK_NUMLOCK,   {num lock}
  1376.     VK_SCROLL :   {scroll lock}
  1377.       begin
  1378.         {if we had a partial command before, we still do}
  1379.         if cpState = stPartial then
  1380.           Result := ccPartial;
  1381.         Exit;
  1382.       end;
  1383.   end;
  1384.  
  1385.   {get out if this key is to be interpreted literally}
  1386.   if cpState = stLiteral then begin
  1387.     cpState := stNone;
  1388.     Exit;
  1389.   end;
  1390.  
  1391.   {get the current shift flags}
  1392.   SS := GetShiftFlags;
  1393.  
  1394.   Command := ccNone;
  1395.   for I := 0 to High(Tables) do begin
  1396.     TmpTbl := GetCommandTable(Tables[I]);
  1397.     if Assigned(TmpTbl) then begin
  1398.       Command := cpScanTable(TmpTbl, K, SS);
  1399.       if Command <> ccNone then
  1400.         Break;
  1401.     end;
  1402.   end;
  1403.  
  1404.   {if we found a match, return command and exit}
  1405.   if Command <> ccNone then begin
  1406.     Result := Command;
  1407.     Exit;
  1408.   end;
  1409.  
  1410.   {if we had a partial command, suppress this key}
  1411.   if cpState = stPartial then
  1412.     Result:= ccSuppress;
  1413.  
  1414.   cpState := stNone;
  1415. end;
  1416.  
  1417. function TOvcCommandProcessor.TranslateKeyUsing(const Tables : array of string; Key : Word; ShiftState : TShiftState) : Word;
  1418.   {-translate a Key and shift-state into a command using the given tables}
  1419. var
  1420.   TmpTbl  : TOvcCommandTable;
  1421.   Command : Word;
  1422.   I       : Integer;
  1423.   SS      : Byte;        {shift flags}
  1424. begin
  1425.   {accept the key if no match found}
  1426.   Result := ccAccept;
  1427.  
  1428.   {check for shift state keys, note partial status and exit}
  1429.   case Key of
  1430.     VK_SHIFT,     {shift}
  1431.     VK_CONTROL,   {ctrl}
  1432.     VK_ALT,       {alt}
  1433.     VK_CAPITAL,   {caps lock}
  1434.     VK_NUMLOCK,   {num lock}
  1435.     VK_SCROLL :   {scroll lock}
  1436.       begin
  1437.         {if we had a partial command before, we still do}
  1438.         if cpState = stPartial then
  1439.           Result := ccPartial;
  1440.         Exit;
  1441.       end;
  1442.   end;
  1443.  
  1444.   {get out if this key is to be interpreted literally}
  1445.   if cpState = stLiteral then begin
  1446.     cpState := stNone;
  1447.     Exit;
  1448.   end;
  1449.  
  1450.   {get the shift flags}
  1451.   SS := (Ord(ssCtrl in ShiftState) * ss_Ctrl) +
  1452.         (Ord(ssShift in ShiftState) * ss_Shift) +
  1453.         (Ord(ssAlt in ShiftState) * ss_Alt);
  1454.  
  1455.   Command := ccNone;
  1456.   for I := 0 to High(Tables) do begin
  1457.     TmpTbl := GetCommandTable(Tables[I]);
  1458.     if Assigned(TmpTbl) then begin
  1459.       Command := cpScanTable(TmpTbl, Key, SS);
  1460.       if Command <> ccNone then
  1461.         Break;
  1462.     end;
  1463.   end;
  1464.  
  1465.   {if we found a match, return command and exit}
  1466.   if Command <> ccNone then begin
  1467.     Result := Command;
  1468.     Exit;
  1469.   end;
  1470.  
  1471.   {if we had a partial command, suppress this key}
  1472.   if cpState = stPartial then
  1473.     Result:= ccSuppress;
  1474.  
  1475.   cpState := stNone;
  1476. end;
  1477.  
  1478.  
  1479. end.
  1480.